// 导入sequelize内置的数据类型，这些数据类型对应数据库的表里的不同类型
const { DataTypes } = require("sequelize");
// 导入数据库连接
const seq = require("../db/seq");

// 模型是 Sequelize 的本质. 模型是代表数据库中表的抽象。

/**
 * 创建(定义)模型（即定义表，创建表）
 * 创建模型有两种方式：
 * 一种：通过调用Sequelize实例的define('模型名')方法，es：sequelize.define('User', {属性}); =》创建一个模型名为 User 的模型，该模型指向一个也名为 User 的表。
 * 另一种：通过扩展Model，如：const { Model } = require('sequelize');class User extends Model {}
 *
 * 表名推断：
 * 请注意，在以上两种方法中，都从未明确定义表名(Users)。但是，给出了模型名称(User)。
 * 默认情况下，当未提供表名时，Sequelize 会自动将模型名的复数写法用作表名（如：User => Users; zd_user => zd_users）。
 * 这种复数是通过称为 inflection 的库在后台完成的，因此可以正确计算不规则的复数(例如 person -> people)。
 * 若在模型配置中手动配置了表名称，则以手动配置的表名称为准。
 *
 * 在一个项目中，一般会给模型名加上一个前缀，这代表是一个统一的项目。
 */
const Goods = seq.define(
  "zd_goods",
  // 模型属性，要和表的字段一一对应
  {
    /**
     * 注意：Sequelize会自动为模型添加以下字段（无需手动定义）：
     * - id: 主键，自增整数，唯一标识每条记录
     * - createdAt: 记录创建时间（若timestamps配置为true时添加）
     * - updatedAt: 记录最后更新时间（若timestamps配置为true时添加）
     * - deletedAt: 记录软删除时间（若paranoid配置为true时添加）
     */

    goods_name: {
      type: DataTypes.STRING, // 该字段的数据类型
      allowNull: false, // 该字段的值是否允许为空
      comment: "商品名称", // 该字段的注释
    },
    goods_price: {
      type: DataTypes.DECIMAL(10, 2), // 定义类型为10进制小数类型，保留两位小数
      allowNull: false,
      comment: "商品价格",
    },
    goods_num: {
      type: DataTypes.INTEGER, // 普通整型
      allowNull: false,
      comment: "商品库存",
    },
    goods_img: {
      type: DataTypes.STRING, // 字符串类型
      allowNull: false,
      comment: "商品图片的url",
    },
  },
  // 模型配置
  {
    // freezeTableName: true, // 是否强制表名称等于模型名称
    /**
     * 表名配置：强制指定表名称
     * 若不设置，Sequelize默认会将模型名复数化作为表名（如模型名'user'会对应表名'users'）
     */
    tableName: "zd_goods",
    /**
     * 是否自动创建 createdAt(创建时刻的时间戳) 和 updatedAt(最新更新的时间戳) 字段，默认值为true。
     * 如果需要自定义这两个字段的名称，可以通过createdAt和updatedAt配置（如createdAt: 'create_time'）。
     */
    timestamps: true,
    /**
     * 将模型定义为paranoid表（即偏执表），开启之后模型删除操作就会变成软删除
     * Sequelize 支持 paranoid 表的概念. 一个 paranoid 表是一个被告知删除记录时不会真正删除它的表.反而一个名为 deletedAt 的特殊列会将其值设置为该删除请求的时间戳.
     * 这意味着偏执表会执行记录的 软删除,而不是 硬删除.
     * 软删除：删除操作只是逻辑删除，不会真正删除数据，而是将deletedAt字段设置为当前时间戳（查询数据时会自动过滤掉deletedAt不为null的记录，Sequelize自动添加WHERE deletedAt IS NULL条件），便于数据恢复和审计
     * 硬删除：将数据从数据库中删除
     * 修改配置后需要重新放开Goods.sync的注释，并重新运行项目，让表结构重新生成（自动增加 deletedAt 字段），运行后再将Goods.sync注释掉
     */
    paranoid: true,
  },
);

/**
 * 模型同步方法：将模型定义同步到数据库，生成对应的表结构
 * sync()方法参数说明：
 * - force: true  强制同步：若表已存在则先删除再创建（会丢失数据，谨慎使用）
 * - force: false（默认）  只在表不存在时创建，表已存在则不做操作
 *
 * 注意事项：
 * 1. 首次运行时可开启同步，生成表结构后建议注释掉
 * 2. 生产环境中不建议使用sync()，推荐使用迁移工具(migrations)管理表结构
 */
// Goods.sync({
//   force: true, // 开发环境初次创建表时使用，后续请注释或改为false
// });

module.exports = Goods;
